﻿using CoreLims.Models.CoreLims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoreLims.Controllers
{
    [Authorize(Roles = "Admin,库存管理")]
    public class InvController : Controller
    {
        private readonly CoreLimsContext dbContext;

        public InvController(CoreLimsContext context)
        {
            dbContext = context;
        }

        public ViewResult InvManager() => View();

        public ViewResult MaterialManager() => View();

        [HttpPost]
        public ViewResult AddMaterial(string MaterialId, string ModalID)
        {
            ViewData["MaterialId"] = MaterialId;
            ViewData["ModalID"] = ModalID;
            return View();
        }

        [HttpPost]
        public ViewResult AddEntryInventory(string MaterialCode, string MaterialName, string ModalID, string EntryInventoryId)
        {
            ViewData["MaterialCode"] = MaterialCode;
            ViewData["MaterialName"] = MaterialName;
            ViewData["ModalID"] = ModalID;
            ViewData["EntryInventoryId"] = EntryInventoryId;
            return View();
        }

        [HttpPost]
        public ViewResult AddOutInventory(string EntryInventoryId, string OutInventoryId, string ModalID)
        {
            ViewData["EntryInventoryId"] = EntryInventoryId;
            ViewData["OutInventoryId"] = OutInventoryId;
            ViewData["ModalID"] = ModalID;
            return View();
        }

        [HttpPost]
        public ViewResult ReturnInventory(string OutInventoryId, string ModalID)
        {
            ViewData["OutInventoryId"] = OutInventoryId;
            ViewData["ModalID"] = ModalID;
            return View();
        }

        [HttpPost]
        public ViewResult SelectMaterial(string ReturnLabId, string MaterialName)
        {
            ViewData["ReturnLabId"] = ReturnLabId;
            ViewData["MaterialName"] = MaterialName;
            return View();
        }

        [HttpPost]
        public ViewResult ViewUseRecords(string OutInventoryId, string ModalID)
        {
            ViewData["OutInventoryId"] = OutInventoryId;
            ViewData["ModalID"] = ModalID;
            return View();
        }

        #region 物料相关
        [HttpPost]
        public JsonResult GetMaterialByCode(string Code)
        {
            var list = INV.Material.getMaterialList(dbContext)
                .Where(x => x.Code == Code).FirstOrDefault();
            return Json(list);
        }

        [HttpPost]
        public JsonResult GetMaterialType1() //获取 type1 数组
        {
            var list = INV.Material.getMaterialList(dbContext)
                .Distinct(new INV.MaterialType1Compare()).Select(s => new { s.Type1 });
            return Json(list);
        }

        [HttpPost]
        public JsonResult GetMaterialType2ByType1(string type1) //获取 type2 数组
        {
            var list = INV.Material.getMaterialList(dbContext)
                .Where(s => s.Type1 == type1)
                .Distinct(new INV.MaterialType2Compare()).Select(s => new { s.Type2 });
            return Json(list);
        }

        [HttpPost]
        public JsonResult GetMaterialListByType(string limit, string offset, string type1, string type2) //根据 type1 和 type2 查询
        {
            List<Material> list;
            var res = new Common.PageHelper();
            if (type2 == null)
            {
                list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1).OrderBy(x => x.Code)
                    .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();
                res.total = list.Count;
                res.rows = list.ToArray();
            }
            else
            {
                list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1 && s.Type2 == type2).OrderBy(x => x.Code)
                    .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();
                res.total = list.Count;
                res.rows = list.ToArray();
            }
            return Json(res);
        }

        [HttpPost]
        public JsonResult GetMaterialCodeAndName(string type1, string type2) //根据 type1 和 type2 查询物料代码和名称
        {
            var list = INV.Material.getMaterialList(dbContext)
                .Where(s => s.Type1 == type1 && s.Type2 == type2)
                .OrderBy(x => x.Code)
                .Select(s => new { s.Code, s.Name });
            return Json(list);
        }

        [HttpPost]
        public JsonResult GetMaterialListByTypeAndEnable(string limit, string offset, string type1, string type2, string isEnable) //根据物料类型和启用状态查询
        {
            List<Material> list;
            var res = new Common.PageHelper();
            if (type2 == null)
            {
                if (isEnable == "true")
                    list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1).OrderBy(x => x.Code)
                        .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();
                else
                    list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1 && s.IsEnable == true).OrderBy(x => x.Code)
                        .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

                res.total = list.Count;
                res.rows = list.Select(s => new { s.Code, s.Name, s.IsEnable }).ToArray();
            }
            else
            {
                if (isEnable == "true")
                    list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1 && s.Type2 == type2).OrderBy(x => x.Code)
                        .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();
                else
                    list = INV.Material.getMaterialList(dbContext).Where(s => s.Type1 == type1 && s.Type2 == type2 && s.IsEnable == true).OrderBy(x => x.Code)
                        .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

                res.total = list.Count;
                res.rows = list.Select(s => new { s.Code, s.Name, s.IsEnable }).ToArray();
            }
            return Json(res);
        }

        [HttpPost]
        public string postAddMaterial(string jsonStr)
        {
            Material material = JsonConvert.DeserializeObject<Material>(jsonStr);  //反序列化，字符串转换为类
            int m = dbContext.Material.Where(s => s.Code == material.Code).Count();

            if (m == 0)
            {
                dbContext.Material.Add(material);
                dbContext.SaveChanges();
                return "物料添加成功！";
            }
            else
                return "物料代码：" + material.Code + " 已经存在！";
        }

        [HttpPost]
        public string UpdateMaterial(string jsonStr)
        {
            Material other = JsonConvert.DeserializeObject<Material>(jsonStr);  //反序列化，字符串转换为类
            var material = dbContext.Material.Where(s => s.Code == other.Code).FirstOrDefault();
            material.Copy(other);
            dbContext.Update(material);
            dbContext.SaveChanges();

            return "物料信息更新成功！";
        }

        [HttpPost]
        public string UpdateMaterialEnable(string MaterialId, string IsEnable)
        {
            var st = INV.Material.UpdateMaterialEnable(dbContext, MaterialId, IsEnable);
            return st;
        }

        [HttpPost]
        public string UpdateMaterialIsReview(string MaterialId, string IsReview)
        {
            var st = INV.Material.UpdateMaterialIsReview(dbContext, MaterialId, IsReview);
            return st;
        }

        [HttpPost]
        public string UpdateMaterialPerson(string MaterialId, string RemindPersonId, string RemindPerson)
        {
            var met = INV.Material.getMaterial(dbContext, MaterialId);
            met.RemindPerson = RemindPerson;
            met.RemindPersonId = RemindPersonId;
            dbContext.Update(met);
            dbContext.SaveChanges();
            return "提醒人更新成功！";
        }

        [HttpPost]
        public string UpdateMaterialGroup(string MaterialId, string RemindGroupId, string RemindGroup)
        {
            var met = INV.Material.getMaterial(dbContext, MaterialId);
            met.RemindGroupId = RemindGroupId;
            met.RemindGroup = RemindGroup;
            dbContext.Update(met);
            dbContext.SaveChanges();
            return "提醒组更新成功！";
        }

        [HttpPost]
        public string DelMaterial(string Code)
        {
            var count = dbContext.Inventory.Where(s => s.MaterialCode == Code && s.Identification == "入库").Count();
            if (count > 0)
                return "物料：" + Code + " 已经存在入库单，不能删除！";

            var material = dbContext.Material.Where(s => s.Code == Code).FirstOrDefault();
            dbContext.Remove(material);
            dbContext.SaveChanges();
            return "物料删除成功！";
        }

        #endregion

        #region 库存单相关
        [HttpPost]
        public JsonResult GetEntryListByMaterialCode(string limit, string offset, string MaterialCode)
        {
            List<Inventory> list;
            var res = new Common.PageHelper();
            list = INV.Inventory.getEntryByMCode(dbContext, MaterialCode)
                    .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

            res.total = INV.Inventory.getEntryByMCode(dbContext, MaterialCode).Count;
            res.rows = list.ToArray();
            return Json(res);
        }

        [HttpPost]
        public JsonResult GetEntryHistoryListByMaterialCode(string limit, string offset, string MaterialCode)
        {
            List<Inventory> list;
            var res = new Common.PageHelper();
            list = INV.Inventory.getEntryHistoryByMCode(dbContext, MaterialCode)
                    .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

            res.total = INV.Inventory.getEntryHistoryByMCode(dbContext, MaterialCode).Count;
            res.rows = list.ToArray();
            return Json(res);
        }

        [HttpPost]
        public JsonResult GetOutListByEntryId(string limit, string offset, string EntryInventorId)
        {
            List<Inventory> list;
            var res = new Common.PageHelper();
            list = INV.Inventory.getOutByEntryId(dbContext, EntryInventorId)
                    .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

            res.total = INV.Inventory.getOutByEntryId(dbContext, EntryInventorId).Count;
            res.rows = list.ToArray();
            return Json(res);
        }

        [HttpPost]
        public string postAddEntryInventory(string jsonStr)
        {
            try
            {
                Inventory other = JsonConvert.DeserializeObject<Inventory>(jsonStr);  //反序列化，字符串转换为类
                Inventory inventory = new Inventory();

                var user = Common.User.getUserByIdentityName(dbContext, HttpContext.User.Identity.Name);
                inventory.OperatorId = user.Id;
                inventory.OperatorName = user.FullName;
                inventory.Copy(other);
                return inventory.AddEntryInventory(dbContext, null);
            }
            catch (Exception ex) { return ex.Message; }
        }

        [HttpPost]
        public string postAddOutInventory(string EntryInventorId, string jsonStr, string StarWFParameters = null)
        {
            Inventory other = JsonConvert.DeserializeObject<Inventory>(jsonStr);  //反序列化，字符串转换为类
            Inventory inventory = new Inventory(EntryInventorId);

            var user = Common.User.getUserByIdentityName(dbContext, HttpContext.User.Identity.Name);
            inventory.OperatorId = user.Id;
            inventory.OperatorName = user.FullName;
            inventory.Copy(other);
            var st = inventory.AddOutInventory(dbContext, EntryInventorId);

            if (st.Contains("成功") && StarWFParameters != null) // 如果前台传过来启动流程的参数，说明该出库单需要走审批流程。
            {
                StarWFParameters swfp = JsonConvert.DeserializeObject<StarWFParameters>(StarWFParameters);
                var wfc = new WorkFlowController(dbContext);
                return wfc.Start(swfp.WorkFlowId, swfp.DomainName, inventory.Id, swfp.ApprovedByID, swfp.ApprovedByName, user, CreatRemind);
            }
            return st;
        }

        /// <summary>
        /// 发起流程，并生成通知消息
        /// </summary>
        /// <param name="DomainId"></param>
        /// <param name="ApprovedByID"></param>
        /// <param name="ApprovedByName"></param>
        /// <param name="workFlow"></param>
        /// <param name="user"></param>
        private string CreatRemind(string DomainId, string ApprovedByID, string ApprovedByName, WorkFlow workFlow, CommonUser user)
        {
            var domain = INV.Inventory.getInventory(dbContext, DomainId);
            workFlow.CreateRuntimeWorkFlow(domain);
            workFlow.RunWorkFlow(handlerType: user.FullName, handlerId: user.Id); // 自动发起
            workFlow.RunWorkFlow(additionalType: WorkFlow.AdditionalType.下一步处理人.ToString(), additionalData: ApprovedByID); //自动完成发起步骤

            var remind = new Remind();
            remind.Title = "出库审批";
            remind.Content = user.FullName + " 发起的库存出库需要您审批！\n物料代码：" + domain.MaterialCode + " 出库单编号：" + domain.InventoryNumber;
            remind.WorkFlowId = workFlow.RuntimeWorkFlow.Id; // 只有在流程发起时，才记录流程ID，这样方便以后查询提醒标题和内容
            remind.UserId = ApprovedByID;
            remind.UserName = ApprovedByName;
            remind.SendRemindId = user.Id;
            remind.SendRemindName = user.FullName;
            dbContext.Remind.Add(remind);
            dbContext.SaveChanges();
            return "出库审批流程发起成功！";
        }

        [HttpPost]
        public JsonResult GetInventory(string InventorId)
        {
            var inventory = INV.Inventory.getInventory(dbContext, InventorId);
            return Json(inventory);
        }

        [HttpPost]
        public JsonResult GetUseInventory(string limit, string offset, string OutInventoryId)
        {
            var list = INV.UseInventory.getUseInventory(dbContext, OutInventoryId)
                           .Skip(int.Parse(offset)).Take(int.Parse(limit)).ToList();

            var res = new Common.PageHelper();
            res.total = INV.UseInventory.getUseInventory(dbContext, OutInventoryId).Count;
            res.rows = list.ToArray();
            return Json(res);
        }

        [HttpPost]
        public string UpdateEntryInventory(string jsonStr)
        {
            try
            {
                Inventory other = JsonConvert.DeserializeObject<Inventory>(jsonStr);  //反序列化，字符串转换为类
                Inventory inventory = dbContext.Inventory.Where(s => s.Id == other.Id).FirstOrDefault();
                inventory.Copy(other);

                var user = Common.User.getUserByIdentityName(dbContext, HttpContext.User.Identity.Name);
                inventory.OperatorId = user.Id;
                inventory.OperatorName = user.FullName;

                dbContext.Inventory.Update(inventory);
                dbContext.SaveChanges();
                return "入库单更新成功！";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

        }

        [HttpPost]
        public string UpdateOutInventory(string jsonStr)
        {
            try
            {
                Inventory other = JsonConvert.DeserializeObject<Inventory>(jsonStr);  //反序列化，字符串转换为类
                Inventory inventory = dbContext.Inventory.Where(s => s.Id == other.Id).FirstOrDefault();
                inventory.Copy(other);

                var user = Common.User.getUserByIdentityName(dbContext, HttpContext.User.Identity.Name);
                inventory.OperatorId = user.Id;
                inventory.OperatorName = user.FullName;

                dbContext.Inventory.Update(inventory);
                dbContext.SaveChanges();
                return "出库单更新成功！";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        [HttpPost]
        public string DelEntryInventory(string Id)
        {
            return INV.Inventory.DelEntryInventory(dbContext, Id);
        }

        [HttpPost]
        public string DelOutInventory(string Id)
        {
            return INV.Inventory.DelOutInventory(dbContext, Id);
        }

        [HttpPost]
        public string ReOrLockEntryInventory(string Id)
        {
            var inventory = INV.Inventory.getInventory(dbContext, Id);
            if (inventory != null)
            {
                if (inventory.Status == "锁定")
                    return inventory.ReLockEntryInventory(dbContext, Id);
                else
                    return inventory.LockEntryInventory(dbContext, Id);
            }
            else
                return "没找到相应的库存单！";
        }

        [HttpPost]
        public async Task<string> ReturnOutInventory(string OutInventoryId, string jsonStr)
        {
            try
            {
                var other = JsonConvert.DeserializeObject<Inventory>(jsonStr);  //反序列化，字符串转换为类
                return await other.ReturnOutInventory(dbContext, OutInventoryId);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        [HttpPost]
        public async Task<string> UseOutInventory(string OutInventoryId, string Quantity, string Note)
        {
            if (!decimal.TryParse(Quantity, out decimal quantity))
                return "领用数量不是有效数字！";

            var user = Common.User.getUserByIdentityName(dbContext, HttpContext.User.Identity.Name);
            var useInventory = new UseInventory();
            try
            {
                useInventory.OutInventoryId = OutInventoryId;
                useInventory.Quantity = quantity;
                useInventory.Note = Note;
                useInventory.UseId = user.Id;
                useInventory.UseName = user.FullName;
                return await useInventory.UseOutInventory(dbContext);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
        #endregion
    }
}
